//@author A0101878B

#include "Storage.h"
#include "Task.h"
#include "assert.h"
#include <string>
#include <vector>
#include <algorithm>
#include <exception>


using namespace std;

const static int FLOATING_TASK	= 0;
const static int TIMED_TASK		= 1;
const static int DEADLINE_TASK	=	 2;

static const string STRING_DONE = "Done";
static const string STRING_FLOATING = "Floating task";
static const string STRING_DEADLINE = "Deadline task";
static const string STRING_TIMED = "Timed task";
static const string STRING_NON = "None";
static const string STATUS_COMPLETED = "Task Completed";
static const string STATUS_INCOMPLETE = "To be Done.";
static const string EMPTY_STRING = "";
static const  char SPACE = ' ';
//static const char SPACE = ' ';
//static const string EMPTY_STRING = "";

bool keywordsFlag;
bool statusFlag;
bool typeFlag;

Storage:: Storage () {

}

Storage :: ~Storage(){

}

int Storage:: displayFromVector (string& ouput, vector<Task>& vector_task){

	istringstream outputStream;
	if (vector_task.size() != 0){
		for (unsigned int i = 0; i < vector_task.size(); i++){
			vector_task[i].outputAllTaskInfo();}
		return SUCCESS_DISPLAY;
	}

	return  ERROR_DISPLAY;
}
int Storage::add(Task toAdd, vector<string>& returnVector) {
	returnVector.clear();

	if (isExisting(toAdd))
		return ERROR_ADD_DUPLICATE; 
	
	addTask (toAdd);
	returnVector =  tasktoStringVector (toAdd);

	return SUCCESS_ADD;
}

int Storage::remove (string nameTobeRemoved,vector<string>& returnVector){

	if(isSuccessfullyRemoved(nameTobeRemoved,returnVector)) {
		return SUCCESS_REMOVE;
	}
	else {
		return ERROR_REMOVE;}
}


int Storage:: mark( string taskName){
	Task* deadlineTask = NULL;
	Task* floatingTask = NULL;
	Task* timedTask = NULL;

	if (searchTaskobj(_deadlineTasks,taskName,deadlineTask)){
		deadlineTask ->setStatus(STATUS_COMPLETED);
		return SUCCESS_MARK;
	}
	if (searchTaskobj(_floatingTasks,taskName,floatingTask)){
		floatingTask->setStatus(STATUS_COMPLETED);
		return SUCCESS_MARK;
	}
	if (searchTaskobj(_timedTasks,taskName,timedTask)){
		timedTask->setStatus(STATUS_COMPLETED);
		return SUCCESS_MARK;
	}
	return ERROR_MARK;
		
}

int Storage::unmark (string taskName){

	Task* deadlineTask = NULL;
	Task* floatingTask = NULL;
	Task* timedTask = NULL;

	if (searchTaskobj(_deadlineTasks,taskName,deadlineTask)){
		deadlineTask ->setStatus(STATUS_INCOMPLETE);
		return SUCCESS_UNMARK;
	}
	if (searchTaskobj(_floatingTasks,taskName,floatingTask)){
		floatingTask->setStatus(STATUS_INCOMPLETE);
		return SUCCESS_UNMARK;
	}
	if (searchTaskobj(_timedTasks,taskName,timedTask)){
		timedTask->setStatus(STATUS_INCOMPLETE);
		return SUCCESS_UNMARK;
	}
	return ERROR_UNMARK;
}

int Storage::searchTaskName (string searchTitle, vector<string>& _tempStorage){ 
	_tempStorage.clear();

	Task* deadlineTask = NULL;
	Task* floatingTask = NULL;
	Task* timedTask = NULL;

	if (searchTaskobj(_deadlineTasks,searchTitle,deadlineTask)){
		_tempStorage = tasktoStringVector(*deadlineTask);
	}
	if (searchTaskobj(_floatingTasks,searchTitle,floatingTask)){
		_tempStorage = tasktoStringVector (*floatingTask);
	}
	if (searchTaskobj(_timedTasks,searchTitle,timedTask)){
		_tempStorage = tasktoStringVector(*timedTask);
	}
	if (!_tempStorage.empty()){
		return SUCCESS_SEARCH;
	}
	else{ 
		return WARNING_SEARCH_NO_RESULT;
	}

}
/*
int Storage:: searchKeywords(string keywords, vector<Task>& _temp){
	_temp.clear();
	vector<string> keyword_vec = extractKeywords (keywords);
	assert (!keyword_vec.empty());

	searchVectors(keyword_vec, _temp);

	if(!_temp.empty())
		return SUCCESS_SEARCH;
	else
		return WARNING_SEARCH_NO_RESULT;

	return ERROR_SEARCH;
}*/

int Storage:: rename (string nameTobeRenamed, string currentName,vector<string>& oldTask, vector<string>& newTask){

	currentName = stringToLower(currentName);
	bool isChanged = false;
	Task temp = Task (nameTobeRenamed, "","","");

	if (isExisting(temp))
		return WARNING_RENAME_CLASH; 

	Task* deadlineTask = NULL;
	Task* floatingTask = NULL;
	Task* timedTask = NULL;

	if (searchTaskobj(_deadlineTasks,currentName,deadlineTask)){
		oldTask = tasktoStringVector(*deadlineTask);
		deadlineTask->setTaskName(nameTobeRenamed);
		newTask = tasktoStringVector(*deadlineTask);
		return SUCCESS_RENAME;
	}
	if (searchTaskobj(_floatingTasks,currentName,floatingTask)){
		oldTask = tasktoStringVector(*floatingTask);
		floatingTask->setTaskName(nameTobeRenamed);
		newTask = tasktoStringVector(*floatingTask);
		return SUCCESS_RENAME;
	}
	if (searchTaskobj(_timedTasks,currentName,timedTask)){
		oldTask = tasktoStringVector(*timedTask);
		timedTask->setTaskName(nameTobeRenamed);
		newTask = tasktoStringVector(*timedTask);
		return SUCCESS_RENAME;
	}


	return ERROR_RENAME;
	
}


int Storage:: reschedule(string taskName, string newStartTime, string newEndTime,vector <string>& oldTask, vector<string>& newTask){
	Task* deadlineTask = NULL;
	Task* floatingTask = NULL;
	Task* timedTask = NULL;

	if (searchTaskobj(_deadlineTasks,taskName,deadlineTask)){
		oldTask = tasktoStringVector(*deadlineTask);
		deadlineTask->setStartTime(newStartTime);
		deadlineTask->setEndTime(newEndTime);
		newTask = tasktoStringVector(*deadlineTask);
		return SUCCESS_RESCHEDULE;
	}
	if (searchTaskobj(_floatingTasks,taskName,floatingTask)){
		oldTask = tasktoStringVector(*floatingTask);
		floatingTask->setStartTime(newStartTime);
		floatingTask->setEndTime(newEndTime);
		newTask = tasktoStringVector(*floatingTask);
		return SUCCESS_RESCHEDULE;
	}
	if (searchTaskobj(_timedTasks,taskName,timedTask)){
		oldTask = tasktoStringVector(*timedTask);
		timedTask->setStartTime(newStartTime);
		timedTask->setEndTime(newEndTime);
		newTask = tasktoStringVector(*timedTask);
		return SUCCESS_RESCHEDULE;
	}

	return ERROR_RESCHEDULE;
	}

int Storage::relocate (string taskName, string newLocation, vector <string>& oldTask, vector <string>& newTask){

	Task* deadlineTask = NULL;
	Task* floatingTask = NULL;
	Task* timedTask = NULL;

	if (searchTaskobj(_deadlineTasks,taskName,deadlineTask)){
		oldTask = tasktoStringVector(*deadlineTask);
		deadlineTask->setVenue(newLocation);
		newTask = tasktoStringVector(*deadlineTask);
		return SUCCESS_RELOCATE;
	}
	if (searchTaskobj(_floatingTasks,taskName,floatingTask)){
		oldTask = tasktoStringVector(*floatingTask);
		floatingTask->setVenue(newLocation);
		newTask = tasktoStringVector(*floatingTask);
		return SUCCESS_RELOCATE;
	}
	if (searchTaskobj(_timedTasks,taskName,timedTask)){
		oldTask = tasktoStringVector(*timedTask);
		timedTask->setVenue(newLocation);
		newTask = tasktoStringVector(*timedTask);
		return SUCCESS_RELOCATE;
	}

	return ERROR_RELOCATE;
}

int Storage:: loadFile (){
	
	vector<string> stringsFromFile;
	int statusCode;

	statusCode = _FileHandler.load(stringsFromFile);

	if(statusCode == SUCCESS_LOAD) {
		loadTasksFromVector(stringsFromFile);
	
	}
//	cout << "shit";
	return ERROR_LOAD_CORRUPTED_DATA;
}


int Storage::saveFile(){

	vector<Task> allTasks;

	fillVectors(allTasks);

	vector<string> allTasksString = taskVecToStringVec(allTasks);

	return _FileHandler.save(allTasksString);
}


int Storage:: displayAll (vector<Task>&_temp){
	_temp.clear();

	fillVectors(_temp);

	if(!_temp.empty())
		return SUCCESS_DISPLAY;
	else
		return WARNING_DISPLAY_NO_RESULT;

	return ERROR_DISPLAY;
}

int Storage:: displayStatus(bool done, vector<Task>&  _temp){
	_temp.clear();

	matchStatus(done, _temp);

	if(!_temp.empty())
		return SUCCESS_DISPLAY;
	else
		return WARNING_DISPLAY_NO_RESULT;

	return ERROR_DISPLAY;

}

int Storage::clearAll(){

	_floatingTasks.clear();
	_deadlineTasks.clear();
	_timedTasks.clear();
	return SUCCESS_CLEAR;
}

int Storage::displayToday(vector<Task>& _temp){

	DateTime start;
	DateTime end;

	setToday(start, end);

	return searchInRange(start, end, _temp);
}



//-------------------------
int Storage::searchInRange(DateTime& start, DateTime& end, vector<Task>& _temp){

	_temp.clear();

	matchInRangeTime(_temp, start, end);

	if(!_temp.empty())
		return SUCCESS_SEARCH;
	else
		return WARNING_SEARCH_NO_RESULT;

	return ERROR_SEARCH;
}
//________________________

int Storage:: searchInRange (string& start, string& end, vector<Task>& _temp){
	_temp.clear();

	if ((start == "")||(end == "")) {
		return ERROR_SEARCH_TIME_EMPTY;
	}

	DateTime start_d = createDateTimefromString (start);
	DateTime end_d = createDateTimefromString (end);

	matchInRangeTime(_temp, start_d, end_d);

	if(!_temp.empty())
		return SUCCESS_SEARCH;
	else
		return WARNING_SEARCH_NO_RESULT;

	return ERROR_SEARCH;

}


bool Storage::isExisting(Task& tasktoCheck  ){

	string taskName = tasktoCheck.getTaskName();
	Task* TaskPtr = NULL;
	return (searchTaskobj(_deadlineTasks,taskName,TaskPtr)||searchTaskobj(_timedTasks,taskName,TaskPtr)||searchTaskobj(_floatingTasks,taskName,TaskPtr));
}

void Storage::addTask(Task toAdd){

	switch(toAdd.determineTaskType()){

	case FLOATING_TASK:
		_floatingTasks.push_back(toAdd);
		break;
	case DEADLINE_TASK:
		_deadlineTasks.push_back(toAdd);
		break;
	case TIMED_TASK:
		_timedTasks.push_back(toAdd);
		break;
	}
}

bool Storage:: isSuccessfullyRemoved(string nameTobeRemove, vector<string>& returnVector){
	for (unsigned int i = 0; i < _floatingTasks.size();i++){
		if (_floatingTasks[i].getTaskName() == nameTobeRemove){
			returnVector =  tasktoStringVector (_floatingTasks[i]);
			_floatingTasks.erase(_floatingTasks.begin()+i);
			return true;}
	}
	for (unsigned int i = 0; i < _deadlineTasks.size();i++){

		if (_deadlineTasks[i].getTaskName() == nameTobeRemove){
			returnVector = tasktoStringVector (_deadlineTasks[i]);
			_deadlineTasks.erase(_deadlineTasks.begin()+i);
			return true;}
	}
	for (unsigned int i = 0; i < _timedTasks.size();i++){
		if (_timedTasks[i].getTaskName() == nameTobeRemove){
			returnVector = tasktoStringVector (_timedTasks[i]);
			_timedTasks.erase(_timedTasks.begin()+i);
			return true;}
	}

	return false;
}
//*************************************************************************************


int Storage::searchEmptySlots(string start_s, string end_s, vector<string>& _temp_s){
	vector<DateTime> _temp;

	if ((start_s == "")||(end_s == "")) {
		return ERROR_SEARCH_TIME_EMPTY;
	}

	DateTime start = createDateTimefromString(start_s);
	DateTime end = createDateTimefromString (end_s);
	_temp.clear();
	_temp_s.clear();

	if(isEmptySlotsPresent(start, end)){
		matchEmptySlots(start, end, _temp);

		for (unsigned int i = 0 ; i < _temp.size(); i++){
			_temp_s.push_back (_temp[i].getDateTimeString());
		}

		return SUCCESS_SEARCH;
	}
	else
		return WARNING_SEARCH_NO_SLOTS;

	return ERROR_SEARCH;
}

bool Storage::isEmptySlotsPresent(DateTime& start, DateTime& end){

	for(unsigned int i = 0; i < _timedTasks.size(); i++){

		if((_timedTasks[i]).getStart().compareTo(start) <= 0 && (_timedTasks[i]).getEnd().compareTo(end) >= 0)
			return false;
	}
	
	return true;
}

void Storage::matchEmptySlots(DateTime& start, DateTime& end, vector<DateTime>& _temp){

	_duplicatedTimed = _timedTasks;

	cutRangeNTasksOutofBound(start, end);

	if(!_duplicatedTimed.empty())
		std::sort(_duplicatedTimed.begin(), _duplicatedTimed.end());

	matchEmptySlotsToTemp(start, end, _temp);
}


void Storage::cutRangeNTasksOutofBound(DateTime& start, DateTime& end){

	Task tempTask;

	for(unsigned int i = 0; i < _duplicatedTimed.size(); i++){
//--------------------------
	//	tempTask = Task("temp", start, end, 2, false, "comment");
		string startTime = start.getDateTimeString();
		string endTime = end.getDateTimeString();
		tempTask = Task("temp",startTime,endTime,"NUS");
//------------------------
		if(!tempTask.isClashingWith(_duplicatedTimed[i])){
			_duplicatedTimed.erase(_duplicatedTimed.begin() + i);
			i--;
		}

		else if(_duplicatedTimed[i].getStart().compareTo(start) <= 0 && isInRange(_duplicatedTimed[i].getEnd(), start, end)){
			start = _duplicatedTimed[i].getEnd();
			_duplicatedTimed.erase(_duplicatedTimed.begin() + i);
			i--;
		}

		else if(_duplicatedTimed[i].getEnd().compareTo(end) >= 0 && isInRange(_duplicatedTimed[i].getStart(), start, end)){
			end = _duplicatedTimed[i].getStart();
			_duplicatedTimed.erase(_duplicatedTimed.begin() + i);
			i--;
		}
	}
}
void Storage::matchEmptySlotsToTemp(DateTime& start, DateTime& end, vector<DateTime>& _temp){

	_temp.push_back(start);


	for(unsigned int i = 0; i < _duplicatedTimed.size(); i++){

		_temp.push_back(_duplicatedTimed[i].getStart());

		while(1){
			if(i != _duplicatedTimed.size() - 1){
				if(isInRange(_duplicatedTimed[i].getEnd(), _duplicatedTimed[i+1].getStart(), _duplicatedTimed[i+1].getEnd()) && i+1 == _duplicatedTimed.size() - 1){
					_temp.push_back(_duplicatedTimed[i+1].getEnd());
					i++;
					break;
				}
				else if(isInRange(_duplicatedTimed[i].getEnd(), _duplicatedTimed[i+1].getStart(), _duplicatedTimed[i+1].getEnd()) && i+1 != _duplicatedTimed.size() - 1){
					i++;
				}
				else{
					_temp.push_back(_duplicatedTimed[i].getEnd());
					break;
				}
			}
			else
			{
				_temp.push_back(_duplicatedTimed[i].getEnd());
				break;
			}
		}
	}

	_temp.push_back(end);
	//_temp_s.push_back(end_s);
}



//-----------------------------------------------------------------------------------------------


void Storage::searchVectors(vector<string> keywords, vector<Task>& _temp){

	_duplicatedFloating = _floatingTasks;
	_duplicatedDeadline = _deadlineTasks;
	_duplicatedTimed= _timedTasks;

	exactMatch(keywords[0], _temp);
	containMatchFirstWord(keywords[0], _temp);
	containBrokenDownMatchall(keywords, _temp);
}

void Storage::exactMatch(string exactString, vector<Task>& _temp){

	stringToLower(exactString);
	

	for(unsigned int i = 0; i < _duplicatedTimed.size(); i++){

		string tempName = _duplicatedTimed[i].getTaskName();
		string tempLoc = _duplicatedTimed[i].getVenue();
		if( (stringToLower(tempName) == exactString) || (stringToLower(tempLoc) == exactString)){
			_temp.push_back(_duplicatedTimed[i]);
			_duplicatedTimed.erase(_duplicatedTimed.begin()+i);
			i--;
		}
	}	

	for(unsigned int i = 0; i < _duplicatedDeadline.size(); i++){

		string tempName = _duplicatedDeadline[i].getTaskName();
		string tempLoc = _duplicatedDeadline[i].getVenue();
	    if( (stringToLower(tempName) == exactString) || (stringToLower(tempLoc) == exactString)){
			_temp.push_back(_duplicatedDeadline[i]);
			_duplicatedDeadline.erase(_duplicatedDeadline.begin()+i);
			i--;
		}
	}

	for(unsigned int i = 0; i < _duplicatedFloating.size(); i++){

		string tempName = _duplicatedFloating[i].getTaskName();
		string tempLoc = _duplicatedFloating[i].getVenue();
	    if( (stringToLower(tempName) == exactString) || (stringToLower(tempLoc) == exactString)){
			_temp.push_back(_duplicatedFloating[i]);
			_duplicatedFloating.erase(_duplicatedFloating.begin()+i);
			i--;
		}
	}
}

void Storage::containMatchFirstWord(string exactString, vector<Task>& _temp){

	stringToLower(exactString);

	for(unsigned int i = 0; i < _duplicatedTimed.size(); i++){

		string tempString = _duplicatedTimed[i].getTaskName();

		if(stringToLower(tempString).find(exactString) != std::string::npos){
			_temp.push_back(_duplicatedTimed[i]);
			_duplicatedTimed.erase(_duplicatedTimed.begin()+i);
			i--;
		}
	}

	for(unsigned int i = 0; i < _duplicatedDeadline.size(); i++){

		string tempString = _duplicatedDeadline[i].getTaskName();

		if(stringToLower(tempString).find(exactString) != std::string::npos){
			_temp.push_back(_duplicatedDeadline[i]);
			_duplicatedDeadline.erase(_duplicatedDeadline.begin()+i);
			i--;
		}
	}

	for(unsigned int i = 0; i < _duplicatedFloating.size(); i++){

		string tempString = _duplicatedFloating[i].getTaskName();

		if(stringToLower(tempString).find(exactString) != std::string::npos){
			_temp.push_back(_duplicatedFloating[i]);
			_duplicatedFloating.erase(_duplicatedFloating.begin()+i);
			i--;
		}
	}
}

void Storage::containBrokenDownMatchall(vector<string> keywords, vector<Task>& _temp){

	for(unsigned int i = 1; i < keywords.size(); i++){

		containMatchFirstWord(keywords[i], _temp);
	}
}
//-----------------------------------------------------------------------------------
bool Storage::isEqual(Task& thisTask, Task& another){

	if (thisTask.getTaskName() == another.getTaskName())
		return true;
	else 
		return false;
}

void Storage::fillVectors  (vector<Task>& _temp){
	std::sort(_floatingTasks.begin(), _floatingTasks.end());
    std:sort(_deadlineTasks.begin(),_deadlineTasks.end());
	std::sort(_timedTasks.begin(),_timedTasks.end());

	_temp = _floatingTasks;
	_temp.insert(_temp.end(), _deadlineTasks.begin(), _deadlineTasks.end());
	_temp.insert(_temp.end(), _timedTasks.begin(), _timedTasks.end());
}
//----------------------
void Storage:: setToday(DateTime& start, DateTime& end){

	time_t time1=time(NULL);
	struct tm time2;
	localtime_s(&time2, &time1);

	int day, month, year;

	day = time2.tm_mday;
	month = time2.tm_mon + 1;
	year = time2.tm_year + 1900;

	start = DateTime(year, month, day);
	end = DateTime(year, month, day, 23, 59, 59);
}
//-----------------------------------------------
void Storage::matchStatus(bool done, vector<Task>& _temp){ //matchStatus won't return the correct type

//	std::sort(_floatingTasks.end() , _floatingTasks.end());

	for(unsigned int i = 0; i < _floatingTasks.size(); i++){
		
		if(convertStringStatustoBool(_floatingTasks[i].getStatus()) == done) // check again
			_temp.push_back(_floatingTasks[i]);
	}
	
	for(unsigned int i = 0; i < _deadlineTasks.size(); i++){
		
		if(convertStringStatustoBool(_deadlineTasks[i].getStatus()) == done) // check again
			_temp.push_back(_deadlineTasks[i]);
	}

	for(unsigned int i = 0; i < _timedTasks.size(); i++){
		
		if(convertStringStatustoBool(_timedTasks[i].getStatus()) == done) // check again
			_temp.push_back(_timedTasks[i]);
	}

}
bool Storage::isInRange(DateTime time, DateTime start, DateTime end){

	return time.compareTo(start) >= 0 && time.compareTo(end) <= 0;
}

//
void Storage::matchInRangeTime(vector<Task>& _temp, DateTime& start, DateTime& end){

	Task tempTask;

	string startTime = start.getDateTimeString();
	string endTime = end.getDateTimeString();
	tempTask = Task ("temp",startTime,endTime,"NUS");

	std::sort(_timedTasks.begin(), _timedTasks.end());
	std::sort(_deadlineTasks.begin(), _deadlineTasks.end());

	for(unsigned int i = 0; i < _timedTasks.size(); i++){

		if(tempTask.isClashingWith(_timedTasks[i]))
			_temp.push_back(_timedTasks[i]);
	}

	for(unsigned int i = 0; i < _deadlineTasks.size(); i++){

		if(isInRange(_deadlineTasks[i].getEnd(), start, end))
			_temp.push_back(_deadlineTasks[i]);
	}
}
//-------------------------

vector<string> Storage::taskVecToStringVec(vector<Task>& allTasks){

	vector<string> taskLines;
	vector<string> temp;

	for (unsigned int i = 0; i < allTasks.size(); i++){
		temp = toStringVector(allTasks[i]);
		taskLines.insert(taskLines.end(), temp.begin(), temp.end());
	}
	return taskLines;
}

void Storage::loadTasksFromVector(vector<string>& stringsFromFile){

	string title, venue, currStr;
	string status, start,end;
/*	int type;
	bool status;
	DateTime start, end;
	*/
	for (unsigned int i = 0; i < stringsFromFile.size(); i++){

		currStr = stringsFromFile[i];

		switch (i % 5){
		case 0:
			title = currStr.substr(7); 
			break;
		case 1:
			status = currStr.substr(8);
			break;
		case 2:
			start = currStr.substr(7);
			break;
		case 3:
			end = currStr.substr(5);
			break;
		case 4:
			venue = currStr.substr(7);
		
			Task tempTask(title, start, end, venue);
			tempTask.setStatus (status);
			tempTask.setTaskType();
			addTask(tempTask);
			break;
		}
	}
}

vector<string> Storage::toStringVector(Task& taskTobeExtracted){
	vector<string> stringVector;
	string s[5] = {
		"Title: " + taskTobeExtracted.getTaskName(),
		"Status: " + taskTobeExtracted.getStatus(), 
		"Start: " + taskTobeExtracted.getStartTime(), 
		"End: " + taskTobeExtracted.getEndTime(), 
		"Venue: " +taskTobeExtracted.getVenue()};

	for(unsigned int i = 0; i < 5; i++){
		stringVector.push_back(s[i]);
	}

	return stringVector;
}

vector<string> Storage::tasktoStringVector(Task& taskTobeExtracted){
	vector<string> stringVector;
	string s[5] = {
		 taskTobeExtracted.getTaskName(),
		  
		 taskTobeExtracted.getStartTime(), 
		 taskTobeExtracted.getEndTime(), 
		 taskTobeExtracted.getVenue(),
	     taskTobeExtracted.getStatus()};

	for(unsigned int i = 0; i < 5; i++){
		stringVector.push_back(s[i]);
	}

	return stringVector;
}


bool Storage::convertStringStatustoBool (string taskAttribute){
	if (taskAttribute == STATUS_COMPLETED)
		return true;
	else 
		if (taskAttribute == STATUS_INCOMPLETE)
		return false;
	return false; 
}


vector<string> Storage::extractKeywords(string str){
	vector<string> keywords;
	vector<string> temp= stringBrokenDown(str, SPACE);
	keywords.push_back(str);
	keywords.insert(keywords.end(),temp.begin(), temp.end());
	return keywords;
}

vector<string> Storage:: stringBrokenDown(string str, char delim){
	vector<string> vec;
	stringstream ss(str);
	string tempStr;
	while (std::getline(ss, tempStr, delim)){
		if (tempStr!=EMPTY_STRING){
			vec.push_back(tempStr);
		}
	}
	return vec;
}

string Storage::stringToLower(string toLowerString){

	std::transform(toLowerString.begin(), toLowerString.end(), toLowerString.begin(), ::tolower);

	return toLowerString;
}

DateTime Storage::createDateTimefromString (string input) {
	try{
		std::replace (input.begin(),input.end(),':',' ');
		std::replace (input.begin(),input.end(),'/',' ');
	} catch(std::exception& nochange){
		std::cerr <<"invalid or corrucpte";
	}
	istringstream inputStream(input);

	int day, month, year, hour, minute, second;
	string dayName;
	string monthName;

	inputStream >> dayName >> monthName >> day >> hour >> minute >> second >> year;

	//inputStream >> day >> month >> year >> hour >> minute >> second;

	string monthNames [] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};

	for (int i = 0; i < 12; i++) {
		if (monthName == monthNames[i]) {
			month = i+1;
		}
	}

	DateTime dateTimeObj(year, month, day, hour, minute);
	return dateTimeObj;
}

 bool Storage::searchTaskobj ( vector<Task>& vectorTask, string name, Task*& TaskPtr){
	 
	 TaskPtr = NULL;
	 name = stringToLower (name);
	 for (unsigned int i = 0; i < vectorTask.size(); i++){
		 if (stringToLower( vectorTask[i].getTaskName()) == name){
			 TaskPtr = &(vectorTask[i]);
			 return true; 
			}
		}

	 return false;
}

 vector <string> Storage:: breakStringintoCombi(string input){
	 vector <string> vectorReturn;
	 for (unsigned int i = 0; i < input.size() ; i ++){
		 for (unsigned int j = i; j < input.size(); j ++){
			 vectorReturn.push_back(input.substr(i,j-i+1));
			}
		}
	 compare c;
	 sort(vectorReturn.begin(),vectorReturn.end(),c);
	 return vectorReturn;
	}

 int Storage:: searchKeywords(string keywords, vector<Task>& _temp){
	 _temp.clear();
	 keywords = stringToLower(keywords);
	 vector<string> keyword; 
	 keyword = breakStringintoCombi(keywords);
	 
	 if (keyword.empty()){
		 return ERROR_EMPTY_INPUT;
		}
	searchVectors(keyword,_temp);
	 
	if(!_temp.empty()){
		if (_temp.size () > 10){
			_temp.resize(10);
		}
		return SUCCESS_SEARCH;
	}
	else {
		return WARNING_SEARCH_NO_RESULT;
	}
	return ERROR_SEARCH;
}
